#include <stdlib.h>

#include "list.h"
#include "stopwatch.h"

stopwatch_t *stopwatch_create() {
	stopwatch_t *stopwatch = malloc(sizeof(stopwatch_t));
	stopwatch->marks = make_list();
	return stopwatch;
}

void stopwatch_start(stopwatch_t *stopwatch) {
	time(&stopwatch->start_time);
	stopwatch->effective_start_time = stopwatch->start_time;
	stopwatch_mark(stopwatch, "START");
}

void stopwatch_pause(stopwatch_t *stopwatch) {
	time(&stopwatch->pause_time);
}

time_t stopwatch_unpause(stopwatch_t *stopwatch) {
	time_t unpause_time = time(NULL);
	// add the time we've been paused to the effecive start time
	stopwatch->effective_start_time += unpause_time - stopwatch->pause_time;
	return unpause_time - stopwatch->pause_time;
}

time_t stopwatch_start_time(stopwatch_t *stopwatch) {
	return stopwatch->start_time;
}

time_t stopwatch_effective_start_time(stopwatch_t *stopwatch) {
	return stopwatch->effective_start_time;
}

void stopwatch_mark(stopwatch_t *stopwatch, char *name) {
	struct mark *m = malloc(sizeof(struct mark));
	m->name = name;
	time(&m->real_time);
	m->time = m->real_time - stopwatch->effective_start_time;
	append_list(stopwatch->marks, m);
}

struct mark *stopwatch_get_mark(stopwatch_t *stopwatch, char *name) {
	list_iter_t *iter = list_get_iter(stopwatch->marks);
	while (list_iter_has_next(iter)) {
		struct mark *m = list_iter_next(iter);
		if (strcmp(name, m->name) == 0) {
			list_iter_destroy(iter);
			return m;
		}
	}
	list_iter_destroy(iter);
	return NULL;
}

time_t stopwatch_get_delay(stopwatch_t *stopwatch, char *name) {
	list_iter_t *iter = list_get_iter(stopwatch->marks);
	while (list_iter_has_next(iter)) {
		struct mark *m = list_iter_next(iter);
		if (strcmp(name, m->name) == 0) {
			struct mark *prev = list_iter_prev(iter);
			time_t prev_time = (prev!=NULL)?prev->time:0;
			list_iter_destroy(iter);
			return m->time - prev_time;
		}
	}
	list_iter_destroy(iter);
	return 0;
}

time_t stopwatch_get_absolute_delay(stopwatch_t *stopwatch, char *name) {
	struct mark *m = stopwatch_get_mark(stopwatch, name);
	if (m != NULL)
		return m->time;
	else
		return 0;
}

time_t stopwatch_get_real_time(stopwatch_t *stopwatch, char *name) {
	struct mark *m = stopwatch_get_mark(stopwatch, name);
	if (m != NULL)
		return m->real_time;
	else
		return 0;
}

void stopwatch_destroy(stopwatch_t *stopwatch) {
	list_iter_t *iter = list_get_iter(stopwatch->marks);
	while (list_iter_has_next(iter)) {
		struct mark *m = list_iter_next(iter);
		free(m);
	}
	list_iter_destroy(iter);
	destroy_list(stopwatch->marks);
	free(stopwatch);
}

